package com.kinroy.briefreport.service.serviceimpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.kinroy.briefreport.dto.Result;
import com.kinroy.briefreport.dto.UserDto;
import com.kinroy.briefreport.entity.User;
import com.kinroy.briefreport.service.ILoginService;
import com.kinroy.briefreport.service.IRegisterService;
import com.kinroy.briefreport.service.IUserService;
import com.kinroy.briefreport.utils.TokenUtils;
import com.kinroy.briefreport.utils.VerificationCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;


import javax.servlet.http.HttpSession;
import java.util.concurrent.TimeUnit;

/**
 * @author kinroy
 */
@Service
@Slf4j
public class LoginServiceImpl implements ILoginService {
    private static final String CODE_PEF = "AuthLogin.";
    @Autowired
    private IUserService userService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private IRegisterService registerService;

    /**
     * 用户登录
     *
     * @param userDto
     * @return
     */
    @Override
    public Result login(UserDto userDto, boolean rememberMe, HttpSession session) {

        //kinroy 2023.12.9 dev01分支重构了一下登录校验，不使用shiro了
        //分有用户名登录和手机登录两种
        if (userDto.getLoginType() == 0) {
            //用户名登录 loginType为：0
            //todo 完成没有shiro的登录逻辑
            if (userDto == null) {
                return Result.fail("登录失败，登录信息有误！");
            }
            //2.查询数据库，看是否已经注册
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(userDto.getName() != null && !userDto.getName().equals(""), User::getName, userDto.getName());
            wrapper.eq(userDto.getPhone() != null && !userDto.getPhone().equals(""), User::getPhone, userDto.getPhone());
            User result = userService.getOne(wrapper);
            if (result == null) {
                return Result.fail("用户不存在，请先完成注册！");
            }

            //3.用户存在，校验密码是否正确
            String afterPassword = userDto.getPassword() + result.getSalt();
            String finalPassword = DigestUtils.md5DigestAsHex(afterPassword.getBytes());

            if (!finalPassword.equals(result.getPassword())) {
                //密码不正确，登录失败
                return Result.fail("密码或账号有误，请重新登录！");
            }
            //todo:4.用户登录成功，返回用户信息+token
            //生成token
            String token = TokenUtils.generateToken(result.getUid(), result.getPassword());
            BeanUtils.copyProperties(result, userDto);
            userDto.setToken(token);

            return Result.ok(userDto);


        } else if (userDto.getLoginType() == 1) {
            //手机号登录 loginType为：0,通过发送验证码的方式来进行登录，验证码存在Redis中，ttl为30S
            String code = null;
            try {
                code = redisTemplate.opsForValue().get(CODE_PEF + userDto.getPhone());
                if (code == null || code.equals("")) {
                    return Result.fail("验证码已过期，请重启获取！");
                }
            } catch (Exception e) {
                e.printStackTrace();
                return Result.fail("验证码已过期，请重启获取！");
            }
            //判断账号是否有注册过，没有注册就默认创建一个账号，注册过就直接验证
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(userDto.getPhone() != null && !userDto.getPhone().equals(""), User::getPhone, userDto.getPhone());
            //todo：报错了处理一下
            User one = userService.getOne(wrapper);
            if (one == null) {
                //没有注册，默认为此号码注册一个账号
                Boolean aBoolean = registerService.fastRegister(userDto.getPhone());
                if (!aBoolean) {
                    Result.fail("未知错误！");
                }
                if (!userDto.getCode().equals(code)) {
                    return Result.fail("验证码错误！");
                }
                //创建新账号成功后返回新用户信息和相应的token
                LambdaQueryWrapper<User> wrapper1 = new LambdaQueryWrapper<>();
                wrapper1.eq(User::getPhone, userDto.getPhone());
                User result = userService.getOne(wrapper1);
                String token = TokenUtils.generateToken(result.getUid(), result.getPassword());
                UserDto userDto1 = new UserDto();
                BeanUtils.copyProperties(result, userDto1);
                userDto1.setToken(token);
                return Result.ok(userDto1);
            }
            if (!userDto.getCode().equals(code)) {
                return Result.fail("验证码错误！");
            }
            //todo:完成没有集成shiro的登录逻辑
            UserDto userDto2 = new UserDto();
            BeanUtils.copyProperties(one, userDto2);
            String token = TokenUtils.generateToken(one.getUid(), one.getPassword());
            userDto2.setToken(token);
            return Result.ok(userDto2);
        }

        return Result.fail("登录失败！未知错误！");
       /* //1.登录校验，看一下参数是否合法
        if (userDto==null){
            return Result.fail("登录失败，登录信息有误！");
        }
        //2.查询数据库，看是否已经注册
        LambdaQueryWrapper<User> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(!userDto.getName().isEmpty(),User::getName,userDto.getName());
        wrapper.eq(!userDto.getPhone().isEmpty(),User::getPhone,userDto.getPhone());
        User result = userService.getOne(wrapper);
        if (result==null){
            return Result.fail("用户不存在，请先完成注册！");
        }

        //3.用户存在，校验密码是否正确
        String afterPassword = userDto.getPassword()+result.getSalt();
        String finalPassword = DigestUtils.md5DigestAsHex(afterPassword.getBytes());

        if (!finalPassword.equals(result.getPassword())){
            //密码不正确，登录失败
            return Result.fail("密码或账号有误，请重新登录！");
        }

        //4.生成token并返回，将token存在Redis中并设定时间
        String token = JwtUtils.createToken(result.getUid());
        redisTemplate.opsForValue().set("token_"+result.getUid(),token,30, TimeUnit.MINUTES);
        return Result.ok(token);*/
    }

    /**
     * 发送验证码，并存入Redis
     *
     * @param phoneNum
     * @return
     */
    @Override
    public String sendVerificationCode(String phoneNum) {
        //生成验证码
        //kinroy 2023.12.9 新增，如何电话是null或者空，不会生成验证码
        if (phoneNum == null || phoneNum.equals("")) {
            return "phoneNum is null";
        }
        String code = VerificationCodeUtils.getCode(4, 2);
        //将验证码存入Redis中并设置ttl (key为手机号，value为验证码)
        redisTemplate.opsForValue().set(CODE_PEF + phoneNum, code, 60, TimeUnit.SECONDS);
        log.info("号码为：" + phoneNum + "  验证码为：" + code);
        return code;
    }

}
